package com.css.sword.knowing.search.test;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;

import com.css.sword.knowing.search.OrderField;
import com.css.sword.knowing.search.SearchField;
import com.css.sword.knowing.search.SearchInput;
import com.css.sword.knowing.search.SearchResult;
import com.css.sword.knowing.search.Searcher;
import com.css.sword.knowing.search.ValueRange;
import com.css.sword.knowing.search.aggregation.AggBucket;
import com.css.sword.knowing.search.aggregation.AggInput;
import com.css.sword.knowing.search.aggregation.AggResult;
import com.css.sword.knowing.search.aggregation.BucketResult;
import com.css.sword.knowing.search.aggregation.MetricsResult;
import com.css.sword.knowing.search.aggregation.SearchAndAggResult;
import com.css.sword.knowing.search.comm.SearchConst;
import com.css.sword.knowing.search.exception.ArgException;

public class BookSearch {
	private String indexName = "";
	private String[] typeName = {};

	private String keyword = "";
	private String catalog1 = "";
	private String catalog2 = "";
	private String catalog3 = "";
	private String publishingTime = "";

	private int pagesize = 10;
	private int pageno = 1;

	public String getIndexName() {
		return indexName;
	}

	public void setIndexName(String indexName) {
		this.indexName = indexName;
	}

	public String[] getTypeName() {
		return typeName;
	}

	public void setTypeName(String[] typeName) {
		this.typeName = typeName;
	}

	public String getKeyword() {
		return keyword;
	}

	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}

	public String getCatalog1() {
		return catalog1;
	}

	public void setCatalog1(String catalog1) {
		this.catalog1 = catalog1;
	}

	public String getCatalog2() {
		return catalog2;
	}

	public void setCatalog2(String catalog2) {
		this.catalog2 = catalog2;
	}

	public String getCatalog3() {
		return catalog3;
	}
	
	public void setCatalog3(String catalog3) {
		this.catalog3 = catalog3;
	}
	
	public int getPagesize() {
		return pagesize;
	}

	public void setPagesize(int pagesize) {
		this.pagesize = pagesize;
	}

	public int getPageno() {
		return pageno;
	}

	public void setPageno(int pageno) {
		this.pageno = pageno;
	}

	public AggBucket setFacetField(String fname, int size)
	{
		AggBucket ab = new AggBucket();
		
		ab.setAggName(fname);
		ab.setField(fname);
		ab.setSize(size);
		ab.setType(SearchConst.AGG_TYPE_TERMS);
		
		return ab;
	}
	
	public String indexSearch(String name) throws IOException,
			ElasticsearchException, ArgException {
		String jsonString = "";

		SearchInput si = new SearchInput();
		si.setIndexName(indexName);
		si.setTypeNames(typeName);
		
		AggInput ai = new AggInput();
		List<AggBucket> abs = new ArrayList<AggBucket>();
		ai.setAggBuckets(abs);
		ai.setIndexName(indexName);
		ai.setTypeNames(typeName);
		
		ai.setSi(si);
		

		ArrayList<SearchField> where = new ArrayList<SearchField>();

		if (catalog1.length() > 0) {
			SearchField sf = new SearchField();
			sf.setField("catalog1");
			sf.setOperator(SearchConst.SEARCH_OPERATOR_MUST);
			sf.setSearchValue(catalog1);
			
			where.add(sf);
		}
		
		if (catalog2.length() > 0) {
			SearchField sf = new SearchField();
			sf.setField("catalog2");
			sf.setOperator(SearchConst.SEARCH_OPERATOR_MUST);
			sf.setSearchValue(catalog2);
			
			where.add(sf);
		}
		
		if (catalog3.length() > 0) {
			SearchField sf = new SearchField();
			sf.setField("catalog3");
			sf.setOperator(SearchConst.SEARCH_OPERATOR_MUST);
			sf.setSearchValue(catalog3);
			
			where.add(sf);
		}

		if (keyword.length() > 0) {
			
			SearchField[] children = new SearchField[8];
			
			SearchField f1 = new SearchField();
			f1.setField("bianjituijian");
			f1.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f1.setSearchValue(keyword);
			children[0] = f1;
			
			SearchField f2 = new SearchField();
			f2.setField("detail");
			f2.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f2.setSearchValue(keyword);
			children[1] = f2;

			SearchField f3 = new SearchField();
			f3.setField("mulu");
			f3.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f3.setSearchValue(keyword);
			children[2] = f3;

			SearchField f4 = new SearchField();
			f4.setField("name");
			f4.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f4.setSearchValue(keyword);
			children[3] = f4;

			SearchField f5 = new SearchField();
			f5.setField("neirongtuijian");
			f5.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f5.setSearchValue(keyword);
			children[4] = f5;

			SearchField f6 = new SearchField();
			f6.setField("qianyan");
			f6.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f6.setSearchValue(keyword);
			children[5] = f6;

			SearchField f7 = new SearchField();
			f7.setField("shidu");
			f7.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f7.setSearchValue(keyword);
			children[6] = f7;

			SearchField f8 = new SearchField();
			f8.setField("subtitle");
			f8.setOperator(SearchConst.SEARCH_OPERATOR_SHOULD);
			f8.setSearchValue(keyword);
			children[7] = f8;

			SearchField sf = new SearchField();
			sf.setChildrenField(children);
			sf.setOperator(SearchConst.SEARCH_OPERATOR_MUST);
			
	//		f.setBoost(1);
			
			where.add(sf);
		}

		si.setSearchFields(where);
		si.setReturnFields(new String[] { "hkey", "img_hkey",
				"name", "subtitle", "price_x", "detail",
				"author", "publishing_time" ,  "publishing", "catalog1", "catalog2", "catalog3"});

		OrderField sort = new OrderField();
		sort.setFieldName("publishing_time");
		sort.setOrder(SearchConst.SEARCH_ORDER_TYPE_DESC);
		si.setOrderFields(new OrderField[]{sort});
		
		si.setSystemID("public");                                                                                                                                                                                        
		si.setFrom((pageno-1) * pagesize);                                                                                                                                                                                                   
		si.setSize(pagesize);
	
		if(catalog1.isEmpty())
		{
			AggBucket ab1 = setFacetField("catalog1", 200);
			AggBucket ab2 = setFacetField("catalog2", 200);
			AggBucket ab3 = setFacetField("catalog3", 200);

			ab1.setAggBuckets(new ArrayList<AggBucket>());
			ab2.setAggBuckets(new ArrayList<AggBucket>());

			ab1.getAggBuckets().add(ab2);
			ab2.getAggBuckets().add(ab3);

			abs.add(ab1);
		}
		
		
		SearchAndAggResult saar = Searcher.makeAggregation(ai);
		

		String[] associate = new String[0];//CssKM.km_associate(name, keyword, 10, false);
		
		jsonString = rss2Json(saar.getSearchResults(), saar.getAggResult(), associate);

		return jsonString; 
		
	//	return rsCount(rss);
	}
	
	private void getBucketResult(XContentBuilder jsonBuilder, Map<String, List<BucketResult>> bMap) throws IOException
	{
		for(String aggName:bMap.keySet())
		{
			List<BucketResult> bucketResults = bMap.get(aggName);
			jsonBuilder.startArray(aggName);
			
			for(BucketResult br: bucketResults)
			{
				Map<String, AggResult> aggResultMap =  br.getBucketAgg();

				if(null==aggResultMap)
					continue;

				Iterator<Map.Entry<String, AggResult>> entries = aggResultMap.entrySet().iterator();  
				  
				if(entries.hasNext()) {  
				  
				    Map.Entry<String, AggResult> entry = entries.next();
				    
				    if(("catalog1".equals(aggName) || "catalog2".equals(aggName)) &&  "0".equals(entry.getKey()))
				        continue;
				    
					jsonBuilder.startObject();
					
				    jsonBuilder.field("name", entry.getKey());
					jsonBuilder.field("count", br.getDocNumber());
	    	    	jsonBuilder.field("total", br.getDocNumber());
	    	    	

	    	    	Map<String, List<BucketResult>> n_bMap = aggResultMap.get(entry.getKey()).getBucketResultMap();
	    	    	if(n_bMap != null)
	    	    		getBucketResult(jsonBuilder, n_bMap);
	    	    	
	    			jsonBuilder.endObject();
				}
			}
            jsonBuilder.endArray();
		} 
	}

	public String rss2Json(List<SearchResult> rss, AggResult ar, String[] associate) throws IOException
	{
		XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
		
		for(SearchResult rs : rss)                                                                                                                                                                                      
		{		
			long count = rs.getTotalNum();
			long pagenum = (long) Math.ceil((double)count/pagesize);
			
			jsonBuilder.startObject();     
			
			jsonBuilder.field("count", rs.getTotalNum());
	        jsonBuilder.field("total", rs.getTotalNum());
	        jsonBuilder.field("pagenum", pagenum);
			                  
			jsonBuilder.startArray("docs");
            List<Map> data = rs.getData();                                                                                                                                                                                           
			String key=null;                                                                                                                                                                                             
			Object value = null;                                                                                                                                                                                         
			for(Map<String,String> fields : data)                                                                                                                                                                        
			{          
				jsonBuilder.startObject();
				Iterator<String> it = fields.keySet().iterator();                                                                                                                                                        
				while(it.hasNext())                                                                                                                                                                                      
				{					
					key = it.next();                                                                                                                                                                                     
					value = fields.get(key);                                                                                                                                                                             
			         
					if("_id".equalsIgnoreCase(key))
						continue;

					jsonBuilder.field(key, value);                                                                                                                                              
				}                                                                                                                                                                                                        
				jsonBuilder.endObject();                                                                                                                                                                                   
			}
			jsonBuilder.endArray();
			
			break;
		}   
		
		jsonBuilder.startObject("facet");

		Map<String, List<BucketResult>> bMap = ar.getBucketResultMap();
		if(null!=bMap)
		{
			getBucketResult(jsonBuilder, bMap);
		}
		jsonBuilder.endObject();
		
		if(associate!=null && associate.length>0)
		{
			jsonBuilder.array("terms", associate);
		}
		else
		{
			jsonBuilder.startArray("terms");
            jsonBuilder.endArray();
		}
        
		jsonBuilder.endObject();  

        String jsonString = jsonBuilder.string();
        
		return jsonString;
	}

	public String rsCount(List<SearchResult> rss) throws IOException {
		long count = 0;

		for (SearchResult rs : rss) {
			count = rs.getTotalNum();
			break;
		}

		return String.valueOf(count);
	}
	
	public String getSearch(String name) throws IOException,
			ElasticsearchException, ArgException {

		XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();

		return indexSearch(name);
	}
	
	private String getString1(String context, String tag, int position)
	{
		String str = context.replaceAll("[ |　]", "");
		String ret = "";
		
		int pos = str.indexOf(tag, position);
		while(pos > 0)
		{
			int npos = str.indexOf("\n", pos+1);
		
			if(npos > pos)
			{
				String s = str.substring(pos, npos);
				
				s = s.replace(tag, "");
				if(s.length() < 5)
				{
					if(ret.length() > 0)
						ret += ",";
					
					ret += s;
				}	
			}
			
			pos = str.indexOf(tag, pos + tag.length());
		}
		return ret;
	}

	public String getDetail(String hkey)
			throws IOException, ElasticsearchException, ArgException {

		XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();

		SearchInput si = new SearchInput();
		si.setIndexName(indexName);
		si.setTypeNames(typeName);

		ArrayList<SearchField> where = new ArrayList<SearchField>();

		if (hkey.length() > 0) {
			SearchField sf = new SearchField();
			sf.setField("hkey");
			sf.setOperator(SearchConst.SEARCH_OPERATOR_MUST);
			sf.setSearchValue(hkey);
			where.add(sf);
		}

		si.setSearchFields(where);
		si.setReturnFields(new String[] { "hkey", "big_img_hkey",
				"name", "author", "book_info", "zuozhejianjie",
				"bianjituijian", "neirongtuijian", "mulu", "shidu",
				"sub_title", "publishing", "publishing_time" });

		si.setSystemID("public");
		si.setFrom(0);
		si.setSize(1);

		List<SearchInput> sis = new ArrayList<SearchInput>();
		sis.add(si);

		List<SearchResult> rss = Searcher.multiIndexSearch(sis);

		for (SearchResult rs : rss) {
			jsonBuilder.startObject();

			List<Map> data = rs.getData();
			String key = null;
			Object value = null;
			for (Map<String, String> fields : data) {
				jsonBuilder.startObject("doc");
				Iterator<String> it = fields.keySet().iterator();
				while (it.hasNext()) {
					key = it.next();
					value = fields.get(key);

					if ("_id".equalsIgnoreCase(key)
							|| "_score".equalsIgnoreCase(key))
						continue;
					
					jsonBuilder.field(key, value);
				}
				jsonBuilder.endObject();

				break;
			}

			break;
		}

		jsonBuilder.endObject();

		String jsonString = jsonBuilder.string();

		return jsonString;
	}

	 private static void getAggResult(AggResult ar) {
			
			List<MetricsResult> l = ar.getMetricsResults();
			if(null!=l)
			{
				getMetricsResult(l);
			}

			Map<String, List<BucketResult>> bMap = ar.getBucketResultMap();
			if(null!=bMap)
			{
				for(String aggName:bMap.keySet())
				{
					List<BucketResult> bucketResults = bMap.get(aggName);
					System.out.println(aggName);
					for(BucketResult br: bucketResults)
					{
						Map<String, AggResult> aggResultMap =  br.getBucketAgg();
						System.out.println("docNumber:" + br.getDocNumber());
						if(null!=aggResultMap)
						{
							for(String bucketKey : aggResultMap.keySet())
							{
								System.out.println("   " + bucketKey);
								getAggResult(aggResultMap.get(bucketKey));
								
							}
						}
						
					}
				}
			}
		}

		private static void getMetricsResult(List<MetricsResult> l) {
			
			for(MetricsResult mr : l)
			{
				System.out.println(mr.getAggName());
				List<Map<String, Number>> metricsList = mr.getMetrics();
				for(Map<String, Number> map : metricsList)
				{
					if(map!=null)
					{
						for(String metricsKey : map.keySet())
						{
							System.out.print(metricsKey + ":");
							System.out.println(map.get(metricsKey));
						}
					}
				}
			}
		}

		private static boolean isChinese(char c)
		{
			Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
			if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
					|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
					|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
					|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
					|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
					|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
					|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
				return true;
			}
			return false;
		}
		
	public static String[] getSuggest(String name, String key, int count, boolean wt) {
		String[] spells = null;
		ArrayList<String> ret = new ArrayList<String>();
		String str = "";
		String cStr = "";
		boolean flag = true;

//		for (int index = 0; index < key.length(); index++) {
//			char ch = key.charAt(index);
//
//			if (isChinese(ch)) {
//				spells = CssKM.km_spell(String.valueOf(ch));
//				if (spells != null && spells.length > 0)
//					str += spells[0];
//				if(flag)
//					cStr += ch;
//			} else {
//				flag = false;
//				str += ch;
//			}
//		}
//
//		String[] words = CssKM.km_suggest(name, str, count*10, wt);
//		if(words != null)
//		{
//			for(int i=0; i<words.length; i++)
//	    	{				
//	    		if(words[i].indexOf(cStr)==0)
//	    			ret.add(words[i]);
//	    		if(ret.size() >= count)
//	    			break;
//	    	}
//		}
		return ret.toArray(new String[ret.size()]);
	}
	
	public static void main(String[] args) throws IOException,
			ElasticsearchException, ArgException {

//		 String[] words = getSuggest("news", "新", 10, false);
//		 System.out.println(Arrays.asList(words));
	

		BookSearch s = new BookSearch();
		
		 s.setIndexName("books");
		 s.setTypeName(new String[]{"book_all"});
		 s.setKeyword("计算机");
	
		 s.setPagesize(1); s.setPageno(1);
	
		 String ret = s.getSearch("book_all");

		 System.out.println("++++++++++++++++++json++++++++++++++++++++");
		 System.out.println(ret);
/*
		String detail = s.getDetail("books", "book_all", "1599039355786886125");
		System.out.println("++++++++++++++++++detail++++++++++++++++++++");
		System.out.println(detail);
*/
		// s.agg();

		// Searcher.terms("artistnews", "news");
		// Searcher.b();
	}
}
